//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package project_recycle_api_serv

import (
	"context"

	"atomgit.com/openlinksaas/api-server/dao"
	"atomgit.com/openlinksaas/api-server/dao/bulletin_dao"
	"atomgit.com/openlinksaas/api-server/dao/idea_dao"
	"atomgit.com/openlinksaas/api-server/dao/issue_dao"
	"atomgit.com/openlinksaas/api-server/dao/project_dao"
	"atomgit.com/openlinksaas/api-server/dao/project_entry_dao"
	"atomgit.com/openlinksaas/api-server/dao/requirement_dao"
	"atomgit.com/openlinksaas/api-server/dao/testcase_dao"
	"atomgit.com/openlinksaas/api-server/dao/user_dao"
	"atomgit.com/openlinksaas/api-server/utils"
	"atomgit.com/openlinksaas/proto-gen-go.git/project_recycle_api"
)

func (apiImpl *ProjectRecycleApiImpl) List(ctx context.Context, req *project_recycle_api.ListRequest) (*project_recycle_api.ListResponse, error) {
	emptyList := []*project_recycle_api.RecycleItemInfo{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_recycle_api.ListResponse{
			Code:     project_recycle_api.ListResponse_CODE_WRONG_SESSION,
			ErrMsg:   "会话不存在",
			ItemList: emptyList,
		}, nil
	}
	_, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_recycle_api.ListResponse{
			Code:     project_recycle_api.ListResponse_CODE_NO_PROJECT,
			ErrMsg:   "项目不存在",
			ItemList: emptyList,
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_recycle_api.ListResponse{
			Code:     project_recycle_api.ListResponse_CODE_NO_PERMISSION,
			ErrMsg:   "没有权限",
			ItemList: emptyList,
		}, nil
	} else if err != nil {
		return nil, err
	}

	count, err := project_dao.RecycleDao.Count(ctx, req.ProjectId, req.FilterByItemType, uint32(req.ItemType))
	if err != nil {
		return nil, err
	}

	recycleItemList, err := project_dao.RecycleDao.List(ctx, req.ProjectId, req.FilterByItemType, uint32(req.ItemType), int64(req.Offset), int64(req.Limit))
	if err != nil {
		return nil, err
	}

	//获取标题
	titleMap, err := apiImpl.getTitleMap(ctx, req.ProjectId, recycleItemList)
	if err != nil {
		return nil, err
	}
	//获取用户信息
	userIdList := []string{}
	for _, recycleItem := range recycleItemList {
		userIdList = append(userIdList, recycleItem.RemoveUserId)
	}
	userItemList, err := user_dao.UserInfoDao.ListById(ctx, userIdList)
	if err != nil {
		return nil, err
	}
	userItemMap := map[string]*user_dao.UserInfoDbItem{}
	for _, userItem := range userItemList {
		userItemMap[userItem.UserId] = userItem
	}
	//生成结果
	retItemList := []*project_recycle_api.RecycleItemInfo{}
	for _, recycleItem := range recycleItemList {
		item := recycleItem.ToRecycleItemInfo()
		item.Title = titleMap[recycleItem.RecycleItemId]
		userItem, ok := userItemMap[recycleItem.RemoveUserId]
		if ok {
			item.RemoveDisplayName = userItem.BasicInfo.DisplayName
			item.RemoveLogoUri = userItem.BasicInfo.LogoUri
		}
		retItemList = append(retItemList, item)
	}

	return &project_recycle_api.ListResponse{
		Code:       project_recycle_api.ListResponse_CODE_OK,
		TotalCount: count,
		ItemList:   retItemList,
	}, nil
}

func (apiImpl *ProjectRecycleApiImpl) getTitleMap(ctx context.Context, projectId string, recycleItemList []*project_dao.RecycleItemInfoDbItem) (map[string]string, error) {
	ideaIdList := []string{}
	requirementIdList := []string{}
	issueIdList := []string{}
	testcaseIdList := []string{}
	bulletinIdList := []string{}
	entryIdList := []string{}
	for _, recycleItem := range recycleItemList {
		if recycleItem.RecycleItemType == uint32(project_recycle_api.RECYCLE_ITEM_TYPE_RECYCLE_ITEM_IDEA) {
			ideaIdList = append(ideaIdList, recycleItem.RecycleItemId)
		} else if recycleItem.RecycleItemType == uint32(project_recycle_api.RECYCLE_ITEM_TYPE_RECYCLE_ITEM_REQUIREMENT) {
			requirementIdList = append(requirementIdList, recycleItem.RecycleItemId)
		} else if recycleItem.RecycleItemType == uint32(project_recycle_api.RECYCLE_ITEM_TYPE_RECYCLE_ITEM_TASK) {
			issueIdList = append(issueIdList, recycleItem.RecycleItemId)
		} else if recycleItem.RecycleItemType == uint32(project_recycle_api.RECYCLE_ITEM_TYPE_RECYCLE_ITEM_BUG) {
			issueIdList = append(issueIdList, recycleItem.RecycleItemId)
		} else if recycleItem.RecycleItemType == uint32(project_recycle_api.RECYCLE_ITEM_TYPE_RECYCLE_ITEM_TESTCASE) {
			testcaseIdList = append(testcaseIdList, recycleItem.RecycleItemId)
		} else if recycleItem.RecycleItemType == uint32(project_recycle_api.RECYCLE_ITEM_TYPE_RECYCLE_ITEM_BULLETIN) {
			bulletinIdList = append(bulletinIdList, recycleItem.RecycleItemId)
		} else {
			entryIdList = append(entryIdList, recycleItem.RecycleItemId)
		}
	}
	titleMap := map[string]string{}
	if len(ideaIdList) > 0 {
		itemList, err := idea_dao.IdeaRecycleDao.ListById(ctx, projectId, ideaIdList)
		if err != nil {
			return nil, err
		}
		for _, item := range itemList {
			titleMap[item.IdeaId] = item.BasicInfo.Title
		}
	}
	if len(requirementIdList) > 0 {
		itemList, err := requirement_dao.RequirementRecycleDao.ListById(ctx, projectId, requirementIdList)
		if err != nil {
			return nil, err
		}
		for _, item := range itemList {
			titleMap[item.RequirementId] = item.BaseInfo.Title
		}
	}
	if len(issueIdList) > 0 {
		itemList, err := issue_dao.IssueRecycleDao.ListById(ctx, projectId, issueIdList)
		if err != nil {
			return nil, err
		}
		for _, item := range itemList {
			titleMap[item.IssueId] = item.BasicInfo.Title
		}
	}
	if len(testcaseIdList) > 0 {
		itemList, err := testcase_dao.CaseRecycleDao.ListById(ctx, projectId, testcaseIdList)
		if err != nil {
			return nil, err
		}
		for _, item := range itemList {
			titleMap[item.CaseId] = item.Title
		}
	}
	if len(bulletinIdList) > 0 {
		itemList, err := bulletin_dao.BulletinRecycleDao.ListById(ctx, projectId, bulletinIdList)
		if err != nil {
			return nil, err
		}
		for _, item := range itemList {
			titleMap[item.BulletinId] = item.Title
		}
	}
	if len(entryIdList) > 0 {
		itemList, err := project_entry_dao.EntryRecycleDao.ListById(ctx, projectId, entryIdList)
		if err != nil {
			return nil, err
		}
		for _, item := range itemList {
			titleMap[item.EntryId] = item.EntryTitle
		}
	}
	return titleMap, nil
}
